package com.zwps.biz.domain.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zwps.biz.domain.converter.RoleConverter;
import com.zwps.biz.domain.service.RoleService;
import com.zwps.biz.api.model.dto.role.AddRoleDTO;
import com.zwps.biz.api.model.dto.role.AddRolePermissionApiDTO;
import com.zwps.biz.api.model.dto.role.SelectRoleDTO;
import com.zwps.biz.api.model.dto.role.UpdateRoleDTO;
import com.zwps.biz.api.model.vo.permission.api.SelectPermissionApiVO;
import com.zwps.biz.api.model.vo.role.UpdateRoleVO;
import com.zwps.biz.dal.db.dao.RoleDAO;
import com.zwps.biz.dal.db.dao.RolePagePermissionDAO;
import com.zwps.biz.dal.db.dao.RolePermissionApiDAO;
import com.zwps.biz.dal.db.dao.UserRoleDAO;
import com.zwps.biz.dal.db.object.*;
import com.zwps.common.core.exception.UserActionException;
import com.zwps.common.core.service.CommonService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
@Slf4j
@AllArgsConstructor
public class RoleServiceImpl implements RoleService, CommonService {

    private RoleDAO roleDAO;

    private UserRoleDAO userRoleDAO;

    private RolePagePermissionDAO rolePagePermissionDAO;

    private RolePermissionApiDAO rolePermissionApiDAO;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addRole(AddRoleDTO dto) {
        RoleDO role = RoleConverter.INSTANCE.toRoleDO(dto);
        if (roleDAO.insert(role) < 1) {
            throw new UserActionException("新增角色失败");
        }

        if (CollectionUtil.isNotEmpty(dto.getPagePermissionIds())) {
            for (String pagePermissionId : dto.getPagePermissionIds()) {
                RolePagePermissionDO rolePagePermissionDO = new RolePagePermissionDO(role.getId(),pagePermissionId);
                if (rolePagePermissionDAO.insert(rolePagePermissionDO) < 1) {
                    throw new UserActionException("新增角色菜单关联失败");
                }
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteRoles(String ids) {

        List<String> idList = Arrays.asList(ids.split(","));
        int result = roleDAO.deleteBatchIds(Arrays.asList(ids.split(",")));
        if (result != idList.size()) {
            long RoleNum = roleDAO.selectCount(Wrappers.lambdaQuery(RoleDO.class).in(RoleDO::getId, idList));
            if (RoleNum > 0) {
                log.error("Delete Roles id[{}] fail, select item {}, delete success {}", ids, idList.size(), result);
                throw new UserActionException("删除失败");
            }
        }
        userRoleDAO.delete(Wrappers.lambdaQuery(UserRoleDO.class).in(UserRoleDO::getRoleId, idList));
        rolePagePermissionDAO.delete(Wrappers.lambdaQuery(RolePagePermissionDO.class).in(RolePagePermissionDO::getRoleId, idList));
        rolePermissionApiDAO.delete(Wrappers.lambdaQuery(RolePermissionApiDO.class).in(RolePermissionApiDO::getRoleId, idList));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateRole(String id, UpdateRoleDTO dto) {
        RoleDO selectdRole = roleDAO.selectById(id);
        if (selectdRole == null) {
            throw new UserActionException("修改的角色不存在");
        }

        LambdaUpdateWrapper<RoleDO> updateCurrentRole = Wrappers.lambdaUpdate(RoleDO.class);
        updateCurrentRole.set(change(dto.getRoleName(), selectdRole.getRoleName()), RoleDO::getRoleName,
                dto.getRoleName());
        updateCurrentRole.set(change(dto.getDescription(), selectdRole.getDescription()), RoleDO::getDescription,
                dto.getDescription());
        updateCurrentRole.set(change(dto.getStatus(), selectdRole.getStatus()), RoleDO::getStatus,
                dto.getStatus());

        if (CollectionUtil.isNotEmpty(dto.getPagePermissionIds())) {
            LambdaQueryWrapper<RolePagePermissionDO> delete = Wrappers.lambdaQuery(RolePagePermissionDO.class);
            delete.eq(RolePagePermissionDO::getRoleId, id);
            rolePagePermissionDAO.delete(delete);
            try {
                for (String pagePermissionId : dto.getPagePermissionIds()) {
                    RolePagePermissionDO rolePagePermissionDO = new RolePagePermissionDO(selectdRole.getId(),pagePermissionId);
                    if (rolePagePermissionDAO.insert(rolePagePermissionDO) < 1) {
                        throw new UserActionException("新增角色菜单关联失败");
                    }
                }
            } catch (DuplicateKeyException e) {
                throw new UserActionException("请勿关联的菜单");
            }
        }else {
            LambdaQueryWrapper<RolePagePermissionDO> delete = Wrappers.lambdaQuery(RolePagePermissionDO.class);
            delete.eq(RolePagePermissionDO::getRoleId, id);
            rolePagePermissionDAO.delete(delete);
        }

        if (StrUtil.isNotEmpty(updateCurrentRole.getSqlSet())) {
            updateCurrentRole.eq(RoleDO::getId, id);
            if (roleDAO.update(null, updateCurrentRole) < 1) {
                throw new UserActionException("修改角色信息失败");
            }
        }
    }

    @Override
    public List<RoleDO> selectRoles(SelectRoleDTO dto) {
        LambdaQueryWrapper<RoleDO> RoleQuery = Wrappers.lambdaQuery(RoleDO.class);
        RoleQuery.like(StrUtil.isNotEmpty(dto.getRoleName()), RoleDO::getRoleName, dto.getRoleName());
        RoleQuery.like(StrUtil.isNotEmpty(dto.getDescription()), RoleDO::getDescription, dto.getDescription());
        RoleQuery.eq(dto.getStatus() != null,RoleDO::getStatus,dto.getStatus());
        return roleDAO.selectList(RoleQuery);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void authorityRolePermission(String roleId, AddRolePermissionApiDTO dto) {
        RoleDO selectRole = roleDAO.selectById(roleId);
        if (selectRole == null) {
            throw new UserActionException("赋权角色不存在");
        }
        try {
            //根据角色id获取已设置接口权限
            LambdaQueryWrapper<RolePermissionApiDO> RolePermissionApiQuery = Wrappers.lambdaQuery(RolePermissionApiDO.class);
            RolePermissionApiQuery.eq(RolePermissionApiDO::getRoleId,roleId);
            List<RolePermissionApiDO> selectList = rolePermissionApiDAO.selectList(RolePermissionApiQuery);
            if(selectList==null || selectList.isEmpty()){
                for (String permissionApiId : dto.getPermissionApiIds()) {
                    RolePermissionApiDO rolePermissionApiDO = new RolePermissionApiDO(selectRole.getId(),permissionApiId);
                    if (rolePermissionApiDAO.insert(rolePermissionApiDO) < 1) {
                        throw new UserActionException("赋值角色接口权限失败");
                    }
                }
            }else {
                Set<String> addPermissionApiIds = new HashSet<>(dto.getPermissionApiIds());
                Set<String> delPermissionApiIds = new HashSet<>();
                for(RolePermissionApiDO rpa : selectList){
                    boolean flag = true;
                    for(String permissionApiId : dto.getPermissionApiIds()){
                        if(StringUtils.isNotBlank(permissionApiId) && permissionApiId.equals(rpa.getPermissionApiId())){
                            addPermissionApiIds.remove(permissionApiId);
                            flag = false;
                            continue;
                        }
                    }
                    if(flag){
                        delPermissionApiIds.add(rpa.getPermissionApiId());
                    }
                }
                if(delPermissionApiIds!=null && !delPermissionApiIds.isEmpty()){
                    rolePermissionApiDAO.deleteBatchRolePermissionApiIds(roleId,delPermissionApiIds);
                }
                if(addPermissionApiIds!=null && !addPermissionApiIds.isEmpty()){
                    rolePermissionApiDAO.saveBatchRolePermissionApiIds(roleId,addPermissionApiIds);
                }
            }
        } catch (DuplicateKeyException e) {
            throw new UserActionException("赋值角色接口权限失败");
        }
    }

    @Override
    public List<SelectPermissionApiVO> selectBelongAuthorityRolePermission(String roleId) {
        return rolePermissionApiDAO.selectBelongAuthorityRolePermission(roleId);
    }

    @Override
    public UpdateRoleVO selectRoleById(String roleId) {
        RoleDO roleDO = roleDAO.selectById(roleId);
        UpdateRoleVO updateRoleVO = new UpdateRoleVO();
        if(roleDO!=null){
            BeanUtils.copyProperties(roleDO,updateRoleVO);
        }

        LambdaQueryWrapper<RolePagePermissionDO> wrapper = new QueryWrapper<RolePagePermissionDO>().lambda();
        wrapper.eq(RolePagePermissionDO::getRoleId,roleId);
        List<RolePagePermissionDO> list = rolePagePermissionDAO.selectList(wrapper);
        List<String> stringList = new ArrayList<>();
        for (RolePagePermissionDO rolePagePermissionDO : list) {
            stringList.add(rolePagePermissionDO.getPagePermissionId());
        }

        HashSet<String> strings = new HashSet<>(stringList);
        updateRoleVO.setPagePermissionIds(strings);

        return updateRoleVO;
    }

}
